package com.hk.core.authentication.security.authentication.accesstoken;

import com.hk.commons.util.JsonUtils;
import com.hk.core.authentication.api.TokenGenerator;
import com.hk.core.authentication.api.UserPrincipal;
import com.hk.core.authentication.security.SecurityUserPrincipal;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AuthenticationConverter;

import java.util.Collection;
import java.util.Map;

@RequiredArgsConstructor
public class AccessTokenAuthenticationConverter implements AuthenticationConverter {

    private final TokenRequestMatcher tokenRequestMatcher;

    private final TokenGenerator tokenGenerator;

    @Setter
    private Class<? extends UserPrincipal> principalClass = SecurityUserPrincipal.class;

    @Override
    public Authentication convert(HttpServletRequest request) {
        String token = tokenRequestMatcher.tokenResolve(request);
        Map<String, Object> claims = tokenGenerator.getClaims(token);
        UserPrincipal principal = toUserPrincipal(claims);
        Collection<? extends GrantedAuthority> authorities;
        if (principal instanceof SecurityUserPrincipal securityUserPrincipal) {
            authorities = securityUserPrincipal.getAuthorities();
        } else {
            authorities = SecurityUserPrincipal.toGrantedAuthority(principal.getRoles(), principal.getPermissions());
        }
        return new AccessTokenAuthenticationToken(principal, authorities);
    }

    private UserPrincipal toUserPrincipal(Map<String, Object> claims) {
        Object subject = claims.get(AccessTokenConstant.SUBJECT);
        return JsonUtils.deserialize(subject.toString(), principalClass);
    }
}
